package com.zx.auth.block.config;

import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import com.zx.security.block.handle.AuthenticationEntryPointImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
import org.springframework.security.oauth2.server.authorization.settings.AuthorizationServerSettings;
import org.springframework.security.web.SecurityFilterChain;

import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.UUID;

/**
 * <p>
 * description: 授权服务器配置 <br>
 * create: 2024-04-19 08:43 <br>
 * </p>
 *
 * @author zhou  xun
 */
@Configuration
public class AuthorizationServerConfig {
    /**
     * 认证失败处理类
     */
    @Autowired
    private AuthenticationEntryPointImpl authenticationEntryPoint;


    /**
     * 配置OAuth2授权服务器的安全过滤器链
     * 这是处理OAuth2和OpenID Connect请求的主要配置
     */
    @Order(Ordered.HIGHEST_PRECEDENCE)
    @Bean
    public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity httpSecurity) throws Exception {
        // 获取OAuth2授权服务器配置器
        OAuth2AuthorizationServerConfigurer configure = OAuth2AuthorizationServerConfigurer.authorizationServer();
        // 启用OpenID Connect 1.0（OIDC）默认配置
        configure.oidc(Customizer.withDefaults());

        // 应用授权服务器配置
        httpSecurity
                // 启用默认OAuth2端点
                .securityMatcher(configure.getEndpointsMatcher())
                // 应用授权服务器配置
                .with(configure, Customizer.withDefaults())
                // 异常处理配置，指定未认证时的处理方式
                .exceptionHandling((exceptions) ->
                        exceptions.authenticationEntryPoint(authenticationEntryPoint)
                )
                // 配置OAuth2资源服务器
                .oauth2ResourceServer(oauth2 ->
                        // 启用JWT（JSON Web Token）默认配置
                        oauth2.jwt(Customizer.withDefaults())
                );

        // 构建并返回安全过滤器链
        return httpSecurity.build();
    }

    /**
     * 配置JWK源，使用注入的密钥对
     */
    @Bean
    public JWKSource<SecurityContext> jwkSource(KeyPair rsaKeyPair) {
        RSAPublicKey rsaPublicKey = (RSAPublicKey) rsaKeyPair.getPublic();
        RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) rsaKeyPair.getPrivate();
        RSAKey rsaKey = new RSAKey.Builder(rsaPublicKey)
                .privateKey(rsaPrivateKey)
                .keyID(UUID.randomUUID().toString())
                .build();
        return new ImmutableJWKSet<>(new JWKSet(rsaKey));
    }

    /**
     * 配置JWT解码器，用于验证JWT令牌
     *
     * @param jwkSource jwk源
     * @return {@link JwtDecoder}
     * @author zhou  xun
     * @since 2025-05-13
     */
    @Bean
    @Primary  // 确保这是默认的 JwtDecoder
    @Order(Ordered.HIGHEST_PRECEDENCE)  // 确保它先于其他 JwtDecoder 初始化
    @ConditionalOnMissingBean(JwtDecoder.class) //只在认证服务器中初始化,只有当Spring容器中不存在JwtDecoder类型的bean时，才会创建被标注的bean
    public JwtDecoder authServerJwtDecoder(JWKSource<SecurityContext> jwkSource) {
        return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);
    }

    /**
     * jwt编码器
     *
     * @param jwkSource jwk源
     * @return {@link JwtEncoder}
     * @author zhou  xun
     * @since 2025-05-13
     */
    @Bean
    public JwtEncoder jwtEncoder(JWKSource<SecurityContext> jwkSource) {
        return new NimbusJwtEncoder(jwkSource);
    }

    /**
     * 配置授权服务器设置
     * 使用默认配置(issuer等)
     */
    @Bean
    public AuthorizationServerSettings authorizationServerSettings() {
        return AuthorizationServerSettings.builder().build();
    }
}